package com.ybear.ybutils.utils

import android.os.Build
import androidx.annotation.RequiresApi

class ValueOf private constructor() {
    companion object {
        const val ZERO = '0'
        const val NULL = "null"
        @JvmStatic
        private val i : ValueOf by lazy { ValueOf() }
        @JvmStatic
        fun with(obj: Any?): ValueOf { return i.value( obj ) }
    }

    private var obj: Any? = null
    private fun value(obj: Any?): ValueOf {
        this.obj = obj
        return this
    }

    override fun toString(): String {
        return try {
            toObject()?.toString() ?: ""
        } catch (e: Exception) {
            ""
        }
    }

    fun toObject(): Any? { return obj }

    @JvmOverloads
    fun toShort(radix: Int = 10): Short {
        return try {
            toNumber().toShort( radix )
        } catch (e: Exception) {
            toDouble().toInt().toShort()
        }
    }

    @JvmOverloads
    fun toInt(radix: Int = 10): Int {
        return try {
            toNumber().toInt( radix )
        } catch (e: Exception) {
            toDouble().toInt().toShort().toInt()
        }
    }

    @JvmOverloads
    fun toLong(radix: Int = 10): Long {
        return try {
            toNumber().toLong( radix )
        } catch (e: Exception) {
            toDouble().toInt().toShort().toLong()
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    fun toUnsignedLong(): Long { return toUnsignedLong( 10 ) }

    @RequiresApi(api = Build.VERSION_CODES.O)
    fun toUnsignedLong(radix: Int): Long {
        return try {
            java.lang.Long.parseUnsignedLong( toNumber(), radix )
        } catch (e: Exception) {
            toLong( radix ).toShort().toLong()
        }
    }

    fun toFloat(): Float {
        return try {
            toNumber().toFloat()
        } catch (e: Exception) {
            toDouble().toFloat()
        }
    }

    fun toDouble(): Double {
        return try {
            toNumber().toDouble()
        } catch (e: Exception) {
            e.printStackTrace()
            0.0
        }
    }

    fun toBoolean(): Boolean {
        val s = toString()
        return java.lang.Boolean.parseBoolean( s ) || "1".equals( s, ignoreCase = true )
    }

    @JvmOverloads
    fun toByte(radix: Int = 10): Byte {
        return try {
            toString().toByte(radix)
        } catch (e: Exception) {
            e.printStackTrace()
            0
        }
    }

    fun toChar(): Char? {
        val cs = toChars()
        return if ( cs.isEmpty() ) null else cs[ 0 ]
    }

    fun toChars(): CharArray {
        return try {
            toString().toCharArray()
        } catch (e: Exception) {
            e.printStackTrace()
            CharArray( 0 )
        }
    }

    @Throws(NullPointerException::class)
    fun toNumber(): String {
        return try {
            val s = toString()
            if ( s.isEmpty() || NULL == s )
                ZERO.toString()
            else
                s.replace(
                        "，".toRegex(), ""
                ).replace(
                        ",".toRegex(), ""
                ).trim { it <= ' ' }
        } catch (e: Exception) {
            e.printStackTrace()
            if( obj == null ) "0" else obj.toString()
        }
    }
}